package service

import (
	"errors"
	"github.com/cn-ygf/go-admin/internal/modular/system/dao"
	"github.com/cn-ygf/go-admin/internal/modular/system/model"
	"github.com/cn-ygf/go-admin/internal/modular/system/vo"
	"sync"
)

var (
	ConfigService = new(configService)
	LoadError     = errors.New("缓存配置失败")
)

// configService 后台配置参数
type configService struct {
	store       sync.Map
	configCount int64
}

// Load 缓存数据
func (s *configService) Load() error {
	s.clearStore()
	list, err := dao.SysConfig.Find()
	if err != nil {
		systemLog.Errorln(err.Error())
		return LoadError
	}
	for _, item := range list {
		s.store.Store(item.ConfigKey, item)
		s.configCount++
	}
	systemLog.Infof("加载 %d 个系统参数缓存成功", s.configCount)
	return nil
}

func (s *configService) Get(key string) *model.SysConfig {
	var (
		c   *model.SysConfig
		err error
	)
	v, ok := s.store.Load(key)
	if !ok {
		c, err = s.GetBy(key)
		if err != nil {
			systemLog.Infof("%s key: %s", err.Error(), key)
			return nil
		}
		s.store.Store(key, c)
	} else {
		c = v.(*model.SysConfig)
	}
	return c
}

func (s *configService) GetBy(key string) (*model.SysConfig, error) {
	return dao.SysConfig.Where(dao.SysConfig.ConfigKey.Eq(key)).First()
}

func (s *configService) clearStore() {
	s.store.Range(func(key, value any) bool {
		s.store.Delete(key)
		return true
	})
	s.configCount = 0
}

func (s *configService) GetList() ([]*model.SysConfig, error) {
	return dao.SysConfig.Find()
}

// QueryList 分页查询系统配置列表
func (s *configService) QueryList(req *vo.QueryConfigListReq) ([]*model.SysConfig, int64, error) {
	var (
		u = dao.SysConfig
		d = u.Where()
	)
	if req.PageSize < 1 {
		req.PageSize = 10
	}
	if req.PageNum < 1 {
		req.PageNum = 1
	}
	if req.ConfigName != "" {
		d = d.Where(u.ConfigName.Like("%" + req.ConfigName + "%"))
	}
	if req.ConfigKey != "" {
		d = d.Where(u.ConfigKey.Eq(req.ConfigKey))
	}
	if req.ConfigType != "" {
		d = d.Where(u.ConfigType.Eq(req.ConfigType))
	}
	if req.Params != nil {
		if req.Params.BeginTime > 0 && req.Params.EndTime > 0 {
			d = d.Where(u.CreatedAt.Gte(req.Params.BeginTime))
			d = d.Where(u.CreatedAt.Lte(req.Params.EndTime))
		}
	}
	return d.FindByPage((req.PageNum-1)*req.PageSize, req.PageSize)
}

// All 查询所有系统配置
func (s *configService) All() ([]*model.SysConfig, error) {
	return dao.SysConfig.Find()
}

// GetByID 根据configId查询系统配置
func (s *configService) GetByID(configId int64) (*model.SysConfig, error) {
	return dao.SysConfig.Where(dao.SysConfig.ConfigID.Eq(configId)).First()
}

// GetByConfigName 根据系统配置名查询
// configName 配置名称
func (s *configService) GetByConfigName(configName string) (*model.SysConfig, error) {
	return dao.SysConfig.Where(dao.SysConfig.ConfigName.Eq(configName)).First()
}

// Add 添加系统配置
func (s *configService) Add(req *vo.AddConfigReq) error {
	if !s.CheckConfigKeyUnique(0, req.ConfigKey) {
		return DictTypeNameUniqueError
	}
	u := dao.SysConfig
	newConfig := &model.SysConfig{
		ConfigName:  req.ConfigName,
		ConfigKey:   req.ConfigKey,
		ConfigValue: req.ConfigValue,
		ConfigType:  req.ConfigType,
		CreateBy:    req.CreateBy,
		Remark:      req.Remark,
	}
	err := u.Create(newConfig)
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	return nil
}

// Update 修改系统配置
func (s *configService) Update(req *vo.EditConfigReq) error {
	u := dao.SysConfig
	_, err := u.Where(u.ConfigID.Eq(req.ConfigId)).Updates(map[string]any{
		u.ConfigName.ColumnName().String():  req.ConfigName,
		u.ConfigKey.ColumnName().String():   req.ConfigKey,
		u.ConfigValue.ColumnName().String(): req.ConfigValue,
		u.ConfigType.ColumnName().String():  req.ConfigType,
		u.Remark.ColumnName().String():      req.Remark,
		u.UpdateBy.ColumnName().String():    req.UpdateBy,
	})
	if err != nil {
		systemLog.Errorln(err.Error())
		return ServerError
	}
	return nil
}

// Delete 删除系统配置
func (s *configService) Delete(configIds []int64) error {
	_, err := dao.SysConfig.Where(dao.SysConfig.ConfigID.In(configIds...)).Delete()
	return err
}

// CheckConfigKeyUnique 检查系统配置key是否已存在
func (s *configService) CheckConfigKeyUnique(configId int64, configKey string) bool {
	if configId == 0 {
		count, err := dao.SysConfig.Where(dao.SysConfig.ConfigKey.Eq(configKey)).Count()
		if err != nil {
			systemLog.Errorln(err.Error())
			return true
		}
		return count < 1
	}
	dict, err := s.GetByID(configId)
	if err != nil {
		systemLog.Errorln(err.Error())
		return true
	}
	if dict.ConfigKey == configKey {
		return true
	}
	count, err := dao.SysConfig.Where(dao.SysConfig.ConfigKey.Eq(configKey)).Count()
	if err != nil {
		systemLog.Errorln(err.Error())
		return true
	}
	return count < 1
}
